#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/time.h>
#include "thread.h"

#define SIZE            100000000
#define SECTION (SIZE/NB_THREAD)
#define NB_THREAD 4

int GLOBAL_VALUE=0;

int TAB[SIZE];

int STO[NB_THREAD];

double getTime(){
	struct timeval tv;
	gettimeofday(&tv,NULL);
	return 1000*tv.tv_sec+tv.tv_usec/1000.0;
}

static void* somme(void* a){
	int i;
	int z = (int)a * SECTION;
	int partsum = 0;

	for(i = z; i < z + SECTION; i++){
		partsum += TAB[i];
	} 
	printf("\tSOMME Threads T[%d...%d] = %d\n", z, z + SECTION, partsum);
	thread_exit((void*) partsum);
} 

static void* p_somme(void* a){
	int i;
	int z = (int) a * SECTION;

	int part_sum = 0;
	for(i = z; i < z + SECTION; i++) {
		part_sum += TAB[i];
	}

	printf("\tSOMME Pthreads T[%d...%d] = %d\n", z, z+ SECTION, part_sum);
	pthread_exit((void*)part_sum);
} 

int main(){
	int i;
	thread_t tid[NB_THREAD];
	pthread_t p_tid[NB_THREAD];
	int err, resultat = 0, p_resultat=0;
	void * p_retval[NB_THREAD];
	void * retval[NB_THREAD];

	for(i = 0; i < SIZE ; i++){
		TAB[i] = i;
	}

	printf("\n\n\t\t\tTableau T de taille %d\n\n", SIZE); 


	/****************/
	/* Avec pthread */
	/****************/

	printf("\nAvec la bibliothèque pthread\n\n"); 

	double p_t1 = getTime();

	for(i = 0; i < NB_THREAD ; i++){
		pthread_create(p_tid+i,NULL,p_somme, (void*)(i));
	}

	for(i = 0; i < NB_THREAD; i++){
		err = pthread_join(p_tid[i], &p_retval[i]);
		assert(!err);
		p_resultat += (int) p_retval[i];
	}

	double p_t2 = getTime();
	/*****************/
	/* Avec thread_t */
	/*****************/

	printf("Avec notre bibliothèque\n\n"); 

	double t1 = getTime();
	for(i = 0; i<NB_THREAD ; i++){
		thread_create(tid+i,somme, (void*)i);
	}

	for(i = 0; i < NB_THREAD ; i++){
		err = thread_join(tid[i], &retval[i]);
		assert(!err);
		resultat += (int)(retval[i]);
	}
	double t2 = getTime();
	long s_ret = 0;
	double st1 = getTime();
	for(i = 0; i < SIZE; i++){
		s_ret += TAB[i];
	}
	double st2 = getTime();
	printf("   1-[Cout de calcul avec thread = %g ms]\n", t2 - t1);
	printf("   2-[Cout de calcul avec pthread = %g ms]\n\n", p_t2 - p_t1);
	printf(" 3-[Cout de calcul en séquentiel = %g ms]\n", st2 - st1);
	//  killMainThread();
	return EXIT_SUCCESS;
}
